之前都是使用RESTful API開發
換工作面試幾輪之後發現有蠻多家公司都在使用gRPC
就多學一個技能,順便做個筆記
希望可以幫助到也是初接觸gRPC的你
每個topic的最後會附上參考資料,建議要進去看過一遍
全名:gRPC (gRPC Remote Procedure Calls)
是Google發起的一個開源遠端程序呼叫 (Remote procedure call) 系統。該系統基於 HTTP/2 協定傳輸,使用Protocol Buffers 作為介面描述語言。
講幾個gRPC的優點,其他更加詳細的內容可以參照Microsoft Docs有更詳細的說明
文件即是程式結構,程式內不用另外寫object mapping資料
文件透過binary直接轉譯成程式,支援多種語言
資料會經過protobuf編碼,人類無法直接看懂資料,安全性相較於JSON較高(但同時也是缺點,因為人看不懂)
效能透過protobuf序列化後效能較好
參考資料:https://docs.microsoft.com/zh-tw/aspnet/core/grpc/comparison?view=aspnetcore-5.0
有的人在第一次看到protobuf的時候可能會注意到有proto2 與 proto3
使用上建議proto3
因為支援更多種語言,也有做出許多改進
詳細請見參考資料
到網址找適合的你OS binary
https://github.com/protocolbuffers/protobuf/releases
解壓縮,在bin資料夾底下有個protoc
執行go get下載binary
go get github.com/golang/protobuf/protoc-gen-go
撰寫protocol文件
詳細規格可以看文件,以下是簡單tutorial.proto範例
//使用proto3
syntax = "proto3";
//定義所屬package
package tutorial;
//定義輸出的路徑,沒有寫會出現提示警告訊息,但是目前都是生成在執行的資料夾下
//option go_package = "./tutorial";
//定義API interface
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}
//定義資料結構
// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}
// The response message containing the greetings
message HelloReply {
  string message = 1;
}
}
轉譯成程式碼
轉化為Go程式的command
protoc --go_out=. *.proto
protoc --go_out=plugins=grpc:. *.proto // 用這個比較好,連grpc的service也會跟著轉譯
Read & Write,proto doc在文末有附上
// ProtoExample ...
func ProtoExample() {
	// 你一定很好奇這個struct在哪,在tutorial.pb.go
	p := HelloRequest{
		Name: "Alice",
	}
	// Writing a Message
	bp, err := proto.Marshal(&p)
	if err != nil {
		log.Fatal(err)
	}
	// Reading a Message
	var data HelloRequest
	if err = proto.Unmarshal(bp, &data); err != nil {
		log.Fatal(err)
	}
	log.Println(&data)
}
下載gRPC package
go get -u google.golang.org/grpc
實作API & Server端
type service struct {
	UnimplementedGreeterServer
}
func (s *service) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &HelloReply{Message: "Hello, " + in.GetName()}, nil
}
// GRPCServer ...
func GRPCServer() {
	addr := "127.0.0.1:8080"
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	log.Println("Server listening on", addr)
	gRPCServer := grpc.NewServer()
	RegisterGreeterServer(gRPCServer, &service{})
	if err := gRPCServer.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
實作Client端
const (
	address     = "127.0.0.1:8080"
	defaultName = "world"
)
// GPRCClient ...
func GPRCClient() {
	// Set up a connection to the server.
	conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := NewGreeterClient(conn)
	// Contact the server and print out its response.
	name := defaultName
	if len(os.Args) > 1 {
		name = os.Args[1]
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r, err := c.SayHello(ctx, &HelloRequest{Name: name})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.GetMessage())
}
參考資料:
這是去google搜尋之後看到鐵人賽的文章使用的GUI測試工具
專門用來對gRPC做使用
使用方法
bloomrpc github:https://github.com/uw-labs/bloomrpc
參考的資料非常多,細節很多
文件要多看,只能盡量把作法跟參考資料給集中
總結步驟的話可以分成